/**
 * 
 */
package br.com.ac.fatureweb.view;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import javax.faces.event.ActionEvent;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.Part;

import br.com.ac.fatureweb.jf.model.Aviso_Debito;
import br.com.ac.fatureweb.jf.model.Calculo;
import br.com.ac.fatureweb.jf.model.Configuracao;
import br.com.ac.fatureweb.jf.model.Debitos;
import br.com.ac.fatureweb.jf.model.Economias;
import br.com.ac.fatureweb.jf.model.EnumTypeCarga;
import br.com.ac.fatureweb.jf.model.Ficha;
import br.com.ac.fatureweb.jf.model.Historico;
import br.com.ac.fatureweb.jf.model.Leiturista;
import br.com.ac.fatureweb.jf.model.Mensagem;
import br.com.ac.fatureweb.jf.model.Ocorrencia;
import br.com.ac.fatureweb.jf.model.Reservatorio;
import br.com.ac.fatureweb.jf.model.Saldo;
import br.com.ac.fatureweb.jf.model.Servicos_cobrar;
import br.com.ac.fatureweb.jf.model.Tarifa;
import br.com.ac.fatureweb.jf.model.Tarifa_social;
import br.com.ac.fatureweb.model.Carga;
import br.com.ac.fatureweb.service.NgcImportacaoBean;
import br.com.ac.fatureweb.utilitary.FacesUtils;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

/**
 * @author aldivone
 *
 */
@Named
@ViewScoped
public class ImportacaoBean implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2254926457921530336L;

	private Part arquivo = null;

	private StringBuilder conteudoArquivo = null;

	@Inject
	private NgcImportacaoBean ngcImportacaoBean;

	/**
	 * 
	 * @return
	 * @throws IOException
	 */
	public String carregarArquivo() throws IOException {

		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

		InputStream inputStream = null;

		try {
			inputStream = arquivo.getInputStream();

			int read = 0;

			final byte[] bytes = new byte[1024];

			while ((read = inputStream.read(bytes)) != -1) {
				outputStream.write(bytes, 0, read);
			}

			conteudoArquivo = new StringBuilder(outputStream.toString());

			FacesUtils.addMessageInformation("Arquivo carregado com sucesso!");

		} catch (IOException e) {

		} finally {
			if (outputStream != null) {
				outputStream.close();
			}
			if (inputStream != null) {
				inputStream.close();
			}
		}
		return null;
	}

	/**
	 * 
	 * @param event
	 */
	@SuppressWarnings("incomplete-switch")
	public void importar(ActionEvent event) {
		try {

			if (conteudoArquivo == null || conteudoArquivo.length() < 0) {
				FacesUtils.addMessageError("Arquivo para"
						+ " processamento não foi carregado.");
			}

			Gson gson = new Gson();

			JsonObject fromJson = gson.fromJson(conteudoArquivo.toString(),
					JsonObject.class);

			Set<Entry<String, JsonElement>> entrySet = fromJson.entrySet();

			Calculo configCalculoSaae = null;
			Configuracao configuracaoSaae = null;
			List<Aviso_Debito> lstAvisoDebito = null;
			List<Debitos> lstDebito = null;
			List<Economias> lstEconomia = null;
			List<Ficha> lstImovel = null;
			List<Historico> lstHistorico = null;
			List<Leiturista> lstLeiturista = null;
			List<Mensagem> lstMensagem = null;
			List<Ocorrencia> lstOcorrencia = null;
			List<Reservatorio> lstReservatorio = null;
			List<Saldo> lstSaldoDebitoCredito = null;
			List<Servicos_cobrar> lstLancamentoFuturo = null;
			List<Tarifa_social> lstTarifaSocial = null;
			List<Tarifa> lstTarifa = null;

			for (Entry<String, JsonElement> entry : entrySet) {
				String key = entry.getKey();

				EnumTypeCarga enumTypeCarga = EnumTypeCarga.valueOF(key);

				if (key == null) {
					FacesUtils.addMessageError("Foi encontrado um tipo novo "
							+ "no processamento da carga. Tipo encontrado: "
							+ key);
					return;
				}

				switch (enumTypeCarga) {
				case CALCULO: {
					configCalculoSaae = gson.fromJson(entry.getValue(),
							Calculo.class);
					break;
				}
				case CONFIGURACAO: {
					configuracaoSaae = gson.fromJson(entry.getValue(),
							Configuracao.class);
					break;
				}
				case AVISO_DEBITO: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Aviso_Debito>>() {
					}.getType();
					lstAvisoDebito = gson.fromJson(entry.getValue(), type);
					break;
				}
				case DEBITOS: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Debitos>>() {
					}.getType();
					lstDebito = gson.fromJson(entry.getValue(), type);
					break;
				}
				case ECONOMIAS: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Economias>>() {
					}.getType();
					lstEconomia = gson.fromJson(entry.getValue(), type);
					break;
				}
				case FICHA: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Ficha>>() {
					}.getType();
					lstImovel = gson.fromJson(entry.getValue(), type);
					break;
				}
				case HISTORICO: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Historico>>() {
					}.getType();
					lstHistorico = gson.fromJson(entry.getValue(), type);
					break;
				}
				case LEITURISTA: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Leiturista>>() {
					}.getType();
					lstLeiturista = gson.fromJson(entry.getValue(), type);
					break;
				}
				case MENSAGEM: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Mensagem>>() {
					}.getType();
					lstMensagem = gson.fromJson(entry.getValue(), type);
					break;
				}
				case OCORRENCIA: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Ocorrencia>>() {
					}.getType();
					lstOcorrencia = gson.fromJson(entry.getValue(), type);
					break;
				}
				case RESERVATORIO: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Reservatorio>>() {
					}.getType();
					lstReservatorio = gson.fromJson(entry.getValue(), type);
					break;
				}
				case SALDO: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Saldo>>() {
					}.getType();
					lstSaldoDebitoCredito = gson.fromJson(entry.getValue(),
							type);
					break;
				}
				case SERVICOS_COBRAR: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Servicos_cobrar>>() {
					}.getType();
					lstLancamentoFuturo = gson.fromJson(entry.getValue(), type);
					break;
				}
				case TARIFA: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Tarifa>>() {
					}.getType();
					lstTarifa = gson.fromJson(entry.getValue(), type);
					break;
				}
				case TARIFA_SOCIAL: {
					Type type = new com.google.gson.reflect.TypeToken<ArrayList<Tarifa_social>>() {
					}.getType();
					lstTarifaSocial = gson.fromJson(entry.getValue(), type);
					break;
				}
				}
			}

			Carga carga = ngcImportacaoBean.importar(configCalculoSaae,
					configuracaoSaae, lstAvisoDebito, lstDebito, lstEconomia,
					lstImovel, lstHistorico, lstLeiturista, lstMensagem,
					lstOcorrencia, lstReservatorio, lstSaldoDebitoCredito,
					lstLancamentoFuturo, lstTarifaSocial, lstTarifa);

			FacesUtils.addMessageInformation("Importado: "
					+ carga.getQtdImovel() + " imóveis e "
					+ carga.getQtdLancamentoFuturo() + " Lançamento futuros.");

			arquivo = null;
			conteudoArquivo = null;
		} catch (Exception ex) {
			arquivo = null;
			conteudoArquivo = null;
			FacesUtils.addMessageError("Erro no processamento da carga.");
			ex.printStackTrace();
		}
	}

	/**
	 * @return the arquivo
	 */
	public Part getArquivo() {
		return arquivo;
	}

	/**
	 * @param arquivo
	 *            the arquivo to set
	 */
	public void setArquivo(Part arquivo) {
		this.arquivo = arquivo;
	}

}
